/// Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Collections.ObjectModel;

namespace Microsoft.VSPowerToys.PackInstallerDataModel
{
	/// <summary>
	/// This class holds the data for a single tool.
	/// </summary>
    public class ToolItem
	{
		public enum SortByField
		{
            None = 0,
            DefaultGroup,
			ToolName,
			Author,
			ReleaseDate,
			CurrentlyInstalled,
			MicrosoftProvidedTool
		}

		private string toolName;

		/// <summary>
		/// The name of the tool
		/// </summary>
		public string ToolName
		{
			get { return this.toolName;}
			set { this.toolName = value; }
		}

		private string author;

		/// <summary>
		/// The author of the tool
		/// </summary>
		public string Author
		{
			get { return this.author; }
			set { this.author = value; }
		}

		private string releaseDate;

		/// <summary>
		/// Release date for the tool
		/// </summary>
		public string ReleaseDate
		{
			get { return this.releaseDate; }
			set { this.releaseDate = value; }
		}

        private Collection<string> tags = new Collection<string>();

        /// <summary>
        /// Tags linked to this tool
        /// </summary>
        public Collection<string> Tags
        {
            get { return tags; }
        }
	
		private string detailedDescription;

		/// <summary>
		/// The full description of the tool
		/// </summary>
		public string DetailedDescription
		{
			get { return this.detailedDescription; }
			set { this.detailedDescription = value; }
		}

		private Uri homepageUrl;

		/// <summary>
		/// URL pointing to the home page of the tool
		/// </summary>
		public Uri HomepageUrl
		{
			get { return this.homepageUrl; }
			set { this.homepageUrl = value; }
		}

		private string productGuid;

		/// <summary>
		/// The GUID that is defined in the tool's MSI file, this gets used to find out if the tool is already installed.
		/// </summary>
		public string ProductGuid
		{
			get { return this.productGuid; }
			set { this.productGuid = value; }
		}

		private bool currentlyInstalled;

		/// <summary>
		/// Whether this tool is currently installed
		/// </summary>
		public bool CurrentlyInstalled
		{
			get { return this.currentlyInstalled; }
			set { this.currentlyInstalled = value; }
		}

		private string versionString;

		/// <summary>
		/// The string associated with this version
		/// </summary>
		public string VersionString
		{
			get { return this.versionString; }
			set { this.versionString = value; }
		}

		private string setupFileName;

		/// <summary>
		/// The filename for the setup package associated with this tool
		/// </summary>
		public string SetupFileName
		{
			get { return this.setupFileName; }
			set { this.setupFileName = value; }
		}

		private Uri setupUrl;

		/// <summary>
		/// The URL to download the MSI file from
		/// </summary>
		public Uri SetupUrl
		{
			get { return this.setupUrl; }
			set { this.setupUrl = value; }
		}

        /// <summary>
        /// The MD5 hash for the setup file that we expect to download
        /// </summary>
        private string setupFileHash;

        public string SetupFileHash
        {
            get { return setupFileHash; }
            set { setupFileHash = value; }
        }

		private bool installTool;

		/// <summary>
		/// Flag to indicate whether this version of the tool should get installed.
		/// </summary>
		public bool InstallTool
		{
			get { return this.installTool; }
			set { this.installTool = value; }
		}

		private bool microsoftProvidedTool;

		/// <summary>
		/// Flag to indicate whether this tool comes from Microsoft
		/// </summary>
		public bool MicrosoftProvidedTool
		{
			get { return microsoftProvidedTool; }
			set { microsoftProvidedTool = value; }
		}

		/// <summary>
		/// String to represent the name of the file whose contents are the license agreement
		/// for the tool
		/// For Example: MS-PL.txt
		/// </summary>
		private string licenseAgreementFileName;

		public string LicenseAgreementFileName
		{
			get { return licenseAgreementFileName; }
			set { licenseAgreementFileName = value; }
		}

		/// <summary>
		/// Uri to represent the URL to download the license agreement from
		/// For Example: http://tempuri.org/MS-PL.txt
		/// </summary>
		private Uri licenseAgreementUrl;

		public Uri LicenseAgreementUrl
		{
			get { return licenseAgreementUrl; }
			set { licenseAgreementUrl = value; }
		}

		private bool hideThisTool;

		public bool HideThisTool
		{
			get { return hideThisTool; }
			set { hideThisTool = value; }
		}

        private string defaultTag;

        /// <summary>
        /// String to define which tag for this tool should be the default group.
        /// </summary>
        public string DefaultTag
        {
            get { return defaultTag; }
            set { defaultTag = value; }
        }

        private UserControl uxControl;

        /// <summary>
        /// Gets or sets the ToolSummaryControl created for this item.
        /// </summary>
        public UserControl UserInterfaceControl
        {
            get { return this.uxControl; }
            set { this.uxControl = value; }
        }

        /// <summary>
        /// Checks whether this tool contains the keyword given
        /// </summary>
        /// <param name="keyword">Keyword to check for</param>
        /// <returns>true if tool contains the keyword</returns>
        public bool ContainsText(string keyword)
        {
            if (String.IsNullOrEmpty(keyword)) return true;
            keyword = keyword.ToLower(System.Globalization.CultureInfo.CurrentCulture);
            return
                this.ToolName.ToLower(System.Globalization.CultureInfo.CurrentCulture).Contains(keyword) ||
                this.DetailedDescription.ToLower(System.Globalization.CultureInfo.CurrentCulture).Contains(keyword) ||
                this.Tags.Contains(keyword) || this.VersionString.Contains(keyword);
        }
	}

    /// <summary>
    /// Comparer for tool item objects.
    /// </summary>
    public class ToolItemComparer : IComparer<ToolItem>
    {
        private ToolItem.SortByField sortField;
        private bool reverseOrder;

        public ToolItemComparer(ToolItem.SortByField field, SortOrder order)
        {
            this.sortField = field;
            if (order == SortOrder.Descending)
            {
                reverseOrder = true;
            }
        }



        #region IComparer<ToolItem> Members

        /// <summary>
        /// Compares two ToolItem objects
        /// </summary>
        /// <param name="x">Object to compare against</param>
        /// <param name="y">Object to be compared</param>
        /// <returns></returns>
        int IComparer<ToolItem>.Compare(ToolItem x, ToolItem y)
        {
            if (y != null && x != null)
            {
                if (reverseOrder)
                {
                    ToolItem temp = x;
                    x = y; y = temp;
                }
                // We want to sort based on the user's selection in the GUI which was
                // passed on down to us.
                switch (this.sortField)
                {
                    case ToolItem.SortByField.ToolName:
                    {
                        return (x.ToolName.CompareTo(y.ToolName));
                    }
                    case ToolItem.SortByField.Author:
                    {
                        int compareResult = (x.Author.CompareTo(y.Author));
                        if (compareResult == 0)
                        {
                            compareResult = (x.ToolName.CompareTo(y.ToolName));
                        }
                        return compareResult;
                    }
                    case ToolItem.SortByField.ReleaseDate:
                    {
                        // We need to convert the date string that came out of the feed and convert it
                        // into a DateTime object...
                        DateTime localDate = DateTime.Parse(x.ReleaseDate, Application.CurrentCulture);
                        DateTime compareToDateTime = DateTime.Parse(y.ReleaseDate, Application.CurrentCulture);
                        int compareResult = (localDate.CompareTo(compareToDateTime));
                        if (compareResult == 0)
                        {
                            compareResult = (x.ToolName.CompareTo(y.ToolName));
                        }
                        return compareResult;
                    }
                    case ToolItem.SortByField.CurrentlyInstalled:
                    {
                        // In cases of a tie we go back and compare names.  That way there's at least
                        // some sort of consistent order.
                        if (x.CurrentlyInstalled == y.CurrentlyInstalled)
                        {
                            return (x.ToolName.CompareTo(y.ToolName));
                        }
                        else
                        {
                            return (x.CurrentlyInstalled.CompareTo(y.CurrentlyInstalled));
                        }
                    }
                    case ToolItem.SortByField.MicrosoftProvidedTool:
                    {
                        // In cases of a tie we go back and compare names.  That way there's at least
                        // some sort of consistent order.
                        if (x.MicrosoftProvidedTool == y.MicrosoftProvidedTool)
                        {
                            return (x.ToolName.CompareTo(y.ToolName));
                        }
                        else
                        {
                            return (x.MicrosoftProvidedTool.CompareTo(y.MicrosoftProvidedTool));
                        }
                    }
                    case ToolItem.SortByField.DefaultGroup:
                    {
                        // In cases of a tie we go back and compare names.  That way there's at least
                        // some sort of consistent order.
                        if (string.Equals(x.DefaultTag, y.DefaultTag, StringComparison.CurrentCulture))
                        {
                            return (x.ToolName.CompareTo(y.ToolName));
                        }
                        else
                        {
                            return (x.DefaultTag.CompareTo(y.DefaultTag));
                        }
                    }
                    default:
                        {
                            return (x.ToolName.CompareTo(y.ToolName));
                        }
                }

            }

            throw new ArgumentException(Strings.ToolDataItemCompareToInputErrorMessage);
        }

        #endregion
    }

}
